package com.hyacinth.dubbo.async;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

/**
 * 异步计算模型
 * @author zhangfb
 * @version 1.0.0.1
 * @since JDK 1.8
 */
public class RPCFuture implements Future<Object> {

    /**
     * 中断当前线程
     * @param mayInterruptIfRunning  true=正在运行则中断
     */
    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        return false;
    }

    /**
     * 判断当前线程是否结束
     */
    @Override
    public boolean isCancelled() {
        return false;
    }

    /**
     * 任务是否完成
     */
    @Override
    public boolean isDone() {
        return false;
    }

    /**
     * 获取任务执行结果
     */
    @Override
    public Object get() throws InterruptedException, ExecutionException {
        return null;
    }

    /**
     * 获取任务执行结果，在超时时间内
     */
    @Override
    public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
        return null;
    }

    /**
     *
     */
    static class Sync extends AbstractQueuedSynchronizer {

        private static final long serialVersionUID = 1L;

        //future status
        private final int done = 1;     //已完成
        private final int pending = 0;  //未执行

        /**
         * 方法用来获取锁，返回true说明线程获取成功继续执行，
         * 一旦返回false则线程加入到等待队列中，等待被唤醒
         * @param arg
         * @return
         */
        @Override
        protected boolean tryAcquire(int arg) {
            return getState() == done;
        }

        /**
         * 用来释放锁
         * @param arg
         * @return
         */
        @Override
        protected boolean tryRelease(int arg) {
            if (getState() == pending ) {
                if (compareAndSetState(pending, done)) {
                    return true;
                } else {
                    return false;
                }
            } else {
                return true;
            }
        }

        public boolean isDone() {
            getState();
            return getState() == done;
        }
    }
}
